-- vlc4dvx-extension.lua -- VLC extension --
--[[
INSTALLATION:
Put the file in the VLC subdir /lua/extensions, by default:
* Windows (all users): %ProgramFiles%\VideoLAN\VLC\lua\extensions\
* Windows (current user): %APPDATA%\VLC\lua\extensions\
* Linux (all users): /usr/share/vlc/lua/extensions/
* Linux (current user): ~/.local/share/vlc/lua/extensions/
* Mac OS X (all users): /Applications/VLC.app/Contents/MacOS/share/lua/extensions/
(create directories if they don't exist)
Restart the VLC.
Then you simply use the extension by going to the "View" menu and selecting it.
--]]

-- defaults
time_format = "[T]"  -- [T]-ime, [O]-ver, [E]-lapsed, [D]-uration, [R]-remaining
osd_position = "top-right"
-- predefined time format patterns
time_formats = {"[T]", "[T] >> [O]", "[E] / [D]", "-[R] / [D]", "-[R] ([T])"}

function descriptor()
	return {
		title = "VLC4DVX";
		version = "1.0";
		author = "oedwards";
		url = 'code.google.com/p/vlc4dvx';
		shortdesc = "DVX interface for VLC";
		description = "<div style=\"background-color:lightgreen;\"><b>VLC4DVX</b> is VLC extension (extension script \"vlc4dvx-extension.lua\") that allows the playback of DVX descriptions of video content through VLC.</div>";
		capabilities = {"input-listener"}
	}
end
function activate()
	input_callback("add")
	create_dialog()
end
function deactivate()
	input_callback("del")
end
function close()
	vlc.deactivate()
end
function input_changed()
	input_callback("toggle")
end

callback=false
function input_callback(action)  -- action=add/del/toggle
	if (action=="toggle" and callback==false) then action="add"
	elseif (action=="toggle" and callback==true) then action="del" end

	local input = vlc.object.input()
	if input and callback==false and action=="add" then
		callback=true
		--vlc.var.add_callback(input, "intf-event", input_events_handler, "Hello world!")
		vlc.var.add_callback(input, "highlight", highlight_handler, "Highlight")
	elseif input and callback==true and action=="del" then
		callback=false
		--vlc.var.del_callback(input, "intf-event", input_events_handler, "Hello world!")
		vlc.var.del_callback(input, "highlight", highlight_handler, "Highlight")
	end
end

--split text where it matches the delimiter
function strsplit(text, delimiter)
    local strfind = string.find
    local strsub = string.sub
    local tinsert = table.insert
    local list = {}
    local pos = 1
    if strfind("", delimiter, 1) then -- this would result in endless loops
        error("delimiter matches empty string!")
    end
    local i=1
    while 1 do
        i=i+1
        local first, last = strfind(text, delimiter, pos)
        if first then -- found?
            tinsert(list,i, strsub(text, pos, first-1))
            pos = last+1
        else
            tinsert(list,i, strsub(text, pos))
        break
        end
    end
    return list
end

function round(what, precision)
if what then return math.floor(what*math.pow(10,precision)+0.5) / math.pow(10,precision) else return "" end
end



t=0
function input_events_handler(var, old, new, data)
	vlc.msg.dbg("function input_events_handler")
--[[
  tt=os.clock()
  if tt>=t then

	vlc.osd.message(tostring(var)..'\n'..tostring(old)..'\n'..tostring(new)..'\n'..tostring(data)..'\n'..tostring(tt-t))
	t=tt

	-- DEBUG
	local item = vlc.input.item()
	if (item == nil) then
	else
		local categories = item:info()
		for cat, infos in pairs(categories) do
			vlc.msg.dbg("+----[ "..cat.." ]")
			vlc.msg.dbg("|")
			for name, value in pairs(infos) do
				vlc.msg.dbg("| "..name..": "..value)
			end
			vlc.msg.dbg("|")
		end
		vlc.msg.dbg( "+----[ end of stream info ]")
	end

	local input = vlc.object.input()
	local item = vlc.input.item()
	local playlist = vlc.object.playlist()
	local vout = vlc.object.vout()
	local aout = vlc.object.aout()

	local s ={}

	--update api version when new data/commands added
	s.apiversion=2
	s.version=vlc.misc.version()
	s.volume=vlc.volume.get()

	if input then
		s.length=math.floor(vlc.var.get(input,"length"))
		s.time=math.floor(vlc.var.get(input,"time"))
		s.position=vlc.var.get(input,"position")
		s.audiodelay=vlc.var.get(input,"audio-delay")
		s.rate=vlc.var.get(input,"rate")
		s.subtitledelay=vlc.var.get(input,"spu-delay")
	else
		s.length=0
		s.time=0
		s.position=0
		s.audiodelay=0
		s.rate=1
		s.subtitledelay=0
	end

	if vout then
		s.fullscreen=vlc.var.get(vout,"fullscreen")
		s.aspectratio=vlc.var.get(vout,"aspect-ratio");
		if s.aspectratio=="" then s.aspectratio = "default" end
	else
		s.fullscreen=0
	end

	if aout then
		local filters=vlc.var.get(aout,"audio-filter")
		local temp=strsplit(filters,":")
		s.audiofilters={}
		local id=0
		for i,j in pairs(temp) do
			s.audiofilters['filter_'..id]=j
			id=id+1
		end
	end

	s.videoeffects={}
	s.videoeffects.hue=round(vlc.config.get("hue"),2)
	s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
	s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
	s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
	s.videoeffects.gamma=round(vlc.config.get("gamma"),2)

	s.state=vlc.playlist.status()
	s.random=vlc.var.get(playlist,"random")
	s.loop=vlc.var.get(playlist,"loop")
	s["repeat"]=vlc.var.get(playlist,"repeat")


	if (includecategories and item) then
		s.information={}
		s.information.category={}
		s.information.category.meta=item:metas()

		local info = item:info()
		for k, v in pairs(info) do
			local streamTable={}
			for k2, v2 in pairs(v) do
				local tag = string.gsub(k2," ","_")
				streamTable[tag]=v2
			end

			s.information.category[k]=streamTable
		end

		s.stats={}

		local statsdata = item:stats()
		for k,v in pairs(statsdata) do
			local tag = string.gsub(k,"_","")
			s.stats[tag]=v
		end

		s.information.chapters=vlc.var.get_list(input, "chapter")
		s.information.titles=vlc.var.get_list(input, "title")

	end

	for i,j in pairs(s) do
		vlc.msg.dbg("DBG: "..tostring(i).." : "..tostring(j))
	end

	-- /DEBUG


	--local systemTime = os.date("%H:%M:%S") -- reads and formats OS time
	if time_format~=nil or time_format~="" then
		osd_output = decode_time_format()
		--vlc.osd.message(osd_output, channel1, osd_position) -- displays time on the screen in a video
	end
	--vlc.msg.info(systemTime)

  end
--]]
end

function highlight_handler(var, old, new, data)

	local input = vlc.object.input()

	if input then

		local xStart = vlc.var.get(input,"x-start")
		local xEnd   = vlc.var.get(input,"x-end")
		local yStart = vlc.var.get(input,"y-start")
		local yEnd   = vlc.var.get(input,"y-end")

		vlc.osd.message(tostring(var)..'\n'..tostring(old)..' '..tostring(new)..'\n'..tostring(data)..'\n'..tostring(xStart)..","..tostring(yStart)..'\n'..tostring(xEnd)..","..tostring(yEnd))

		-- Take a video snapshot
		--[[

		var_Create( p_vout, "snapshot-path", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
		var_Create( p_vout, "snapshot-prefix", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
		var_Create( p_vout, "snapshot-format", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
		var_Create( p_vout, "snapshot-preview", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
		var_Create( p_vout, "snapshot-sequential",
					VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
		var_Create( p_vout, "snapshot-num", VLC_VAR_INTEGER );
		var_SetInteger( p_vout, "snapshot-num", 1 );
		var_Create( p_vout, "snapshot-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
		var_Create( p_vout, "snapshot-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );


		var_SetInteger( p_vout, "snapshot-width", i_width);
		var_SetInteger( p_vout, "snapshot-height", i_height );
		var_SetString( p_vout, "snapshot-path", psz_filepath );
		var_SetString( p_vout, "snapshot-format", "png" );
		var_TriggerCallback( p_vout, "video-snapshot" );

		var_SetString( p_vout->p_libvlc, "snapshot-file", psz_filename );

		--]]

		-- Take a screen snapshot, which we'll pass through OCR and TTS to read out the highlighted menu item
		--[[
		local vout = vlc.object.vout()
		if vout then
			--vlc.var.set(vout,"snapshot-path",snapshotPath)
			--vlc.var.set(vout,"snapshot-format","png")
			vlc.var.set(vout,"snapshot-preview",false)
			vlc.var.set(vout,"video-snapshot",nil)

			vlc.var.add_callback(vlc.object.libvlc(), "snapshot-file", snapshot_handler, {xxStart = xStart, xxEnd = xEnd, yyStart = yStart, yyEnd = yEnd })

		else
			vlc.msg.dbg("VLC4DVX: Couldn't find vout")
		end
		--]]

		-- DEBUG
		--[[
		local item = vlc.input.item()
		if (item == nil) then
		else
			local categories = item:info()
			for cat, infos in pairs(categories) do
				vlc.msg.dbg("+----[ "..cat.." ]")
				vlc.msg.dbg("|")
				for name, value in pairs(infos) do
					vlc.msg.dbg("| "..name..": "..value)
				end
				vlc.msg.dbg("|")
			end
			vlc.msg.dbg( "+----[ end of stream info ]")
		end

		local input = vlc.object.input()
		local item = vlc.input.item()
		local playlist = vlc.object.playlist()
		local vout = vlc.object.vout()
		local aout = vlc.object.aout()

		local s ={}

		--update api version when new data/commands added
		s.apiversion=2
		s.version=vlc.misc.version()
		s.volume=vlc.volume.get()

		if input then
			s.length=math.floor(vlc.var.get(input,"length"))
			s.time=math.floor(vlc.var.get(input,"time"))
			s.position=vlc.var.get(input,"position")
			s.audiodelay=vlc.var.get(input,"audio-delay")
			s.rate=vlc.var.get(input,"rate")
			s.subtitledelay=vlc.var.get(input,"spu-delay")
		else
			s.length=0
			s.time=0
			s.position=0
			s.audiodelay=0
			s.rate=1
			s.subtitledelay=0
		end

		if vout then
			s.fullscreen=vlc.var.get(vout,"fullscreen")
			s.aspectratio=vlc.var.get(vout,"aspect-ratio");
			if s.aspectratio=="" then s.aspectratio = "default" end
		else
			s.fullscreen=0
		end

		if aout then
			local filters=vlc.var.get(aout,"audio-filter")
			local temp=strsplit(filters,":")
			s.audiofilters={}
			local id=0
			for i,j in pairs(temp) do
				s.audiofilters['filter_'..id]=j
				id=id+1
			end
		end

		s.videoeffects={}
		s.videoeffects.hue=round(vlc.config.get("hue"),2)
		s.videoeffects.brightness=round(vlc.config.get("brightness"),2)
		s.videoeffects.contrast=round(vlc.config.get("contrast"),2)
		s.videoeffects.saturation=round(vlc.config.get("saturation"),2)
		s.videoeffects.gamma=round(vlc.config.get("gamma"),2)

		s.state=vlc.playlist.status()
		s.random=vlc.var.get(playlist,"random")
		s.loop=vlc.var.get(playlist,"loop")
		s["repeat"]=vlc.var.get(playlist,"repeat")


		if (includecategories and item) then
			s.information={}
			s.information.category={}
			s.information.category.meta=item:metas()

			local info = item:info()
			for k, v in pairs(info) do
				local streamTable={}
				for k2, v2 in pairs(v) do
					local tag = string.gsub(k2," ","_")
					streamTable[tag]=v2
				end

				s.information.category[k]=streamTable
			end

			s.stats={}

			local statsdata = item:stats()
			for k,v in pairs(statsdata) do
				local tag = string.gsub(k,"_","")
				s.stats[tag]=v
			end

			s.information.chapters=vlc.var.get_list(input, "chapter")
			s.information.titles=vlc.var.get_list(input, "title")

		end

		for i,j in pairs(s) do
			vlc.msg.dbg("DBG: "..tostring(i).." : "..tostring(j))
		end
		--]]
		-- /DEBUG

	end
end

function snapshot_handler(var, old, new, data)
	vlc.msg.info("SNAPSHOT TAKEN "..tostring(new).." "..data.xxStart.." "..data.xxEnd.." "..data.yyStart.." "..data.yyEnd)

	--vlc.var.del_callback(vlc.object.libvlc(), "snapshot-file", snapshot_handler, {})

	-- Now do the background OCR & TTS

end

function decode_time_format()
end

function create_dialog()
	w = vlc.dialog("VLC4DVX")
	--w1 = w:add_label("Time format: \\ Position:",1,1,2,1)
	w1 = w:add_label("<b>Time format:</b>",1,1,1,1)
	w01 = w:add_label("<b>\\ Position:</b>",2,1,1,1)
	w2 = w:add_dropdown(3,1,1,1)
		w2:add_value("top-left", 1)
		w2:add_value("top", 2)
		w2:add_value("top-right", 3)
		w2:add_value("left", 4)
		w2:add_value("center", 5)
		w2:add_value("right", 6)
		w2:add_value("bottom-left", 7)
		w2:add_value("bottom", 8)
		w2:add_value("bottom-right", 9)
			w2:set_text(osd_position)
	w3 = w:add_text_input(time_format,1,2,3,1)
	w4 = w:add_dropdown(1,3,2,1)
		w4:add_value("", 1)
		for i=1,#time_formats do
			w4:add_value(time_formats[i], i+1)
		end
			w4:set_text("")
	w10 = w:add_button("START", click_START,1,4,1,1)
	w11 = w:add_button("STOP", click_STOP,2,4,1,1)
	w12 = w:add_button(">> PUT^IN", click_PUTIN,3,3,1,1)
	w13 = w:add_button("HELP", click_HELP,3,4,1,1)
end
function click_STOP()
	time_format = ""
end
function click_START()
	time_format = w3:get_text()
	osd_position = w2:get_text()
end
function click_PUTIN()
	w3:set_text(w4:get_text())
	w4:set_text("")
	w:update()
end
function click_HELP()
	local help_text=""
.."<div style=\"background-color:lightgreen;\"><b>VLC4DVX</b> is VLC extension (extension script \"vlc4dvx-extension.lua\") that allows the playback of DVX descriptions of video content through VLC.</div>"
.."<hr />"
.."<center><b><a style=\"background-color:#FF7FAA;\">&nbsp;Instructions&nbsp;</a></b></center>"
.."<b><a style=\"background-color:#FF7FAA;\">1.)</a></b> Choose a desired <b><a style=\"background-color:lightblue;\">position</a></b> from the drop-down menu.<br />"
.."<b><a style=\"background-color:#FF7FAA;\">2.)</a></b> In <b><a style=\"background-color:lightblue;\">time format</a></b> input field write some time pattern containing time tags. The list of available tags is below.<br />"
.."You can use predefined pattern from the drop-down menu. Choose one and put it in the time format field by pressing <b><nobr><a style=\"background-color:silver;\">[ >> PUT^IN ]</a></nobr></b> button.<br />"
.."<b><a style=\"background-color:#FF7FAA;\">3.)</a></b> Press <b><nobr><a style=\"background-color:silver;\">[ START ]</a></nobr></b> button for changes to take effect.<br /><br />"
.."<b>Following <a style=\"background-color:#FF7FAA;\">time tags</a> can be used within time format pattern:</b>"
.."<div style=\"background-color:#FF7FAA;\">"
.."<b>&nbsp;[T]</b> - actual system time;<br />"
.."<b>&nbsp;[O]</b> - time when video will be over;<br />"
.."<b>&nbsp;[E]</b> - elapsed time (current playback position);<br />"
.."<b>&nbsp;[R]</b> - remaining time;<br />"
.."<b>&nbsp;[D]</b> - duration (length);</div>"
.." > They are automatically replaced with actual time values on the screen.<br />"
.." > If duration value is not available then [D], [R], [O] is replaced with \"--:--\".<br />"
.." > You can also use some short descriptions or put some delimiters among time tags.<br />"
.."<div style=\"background-color:#FFFF7F;\"><b>OSD text format</b> can be customised within internal VLC settings:<br />"
.."Tools > Preferences > (Show settings - Simple) > Subtitles / OSD<br />"
.."Tools > Preferences > (Show settings - All) > +Video > +Subtitles / OSD > -Text renderer<br />"
.."Do not forget to Save and restart VLC for changes to take effect!</div>"
.."<hr />"
.."<div style=\"background-color:lightblue;\">"
.."<b>Homepage:</b> <a href=\"http://forum.videolan.org/viewtopic.php?f=29&t=97639#p332364\">VLC extension: Time</a><br />"
.."<b>Forum:</b> <a href=\"http://forum.videolan.org/viewforum.php?f=29\">Scripting VLC in Lua</a><br />"
.."Please, visit us and bring some new ideas.<br />"
.."Learn how to write own scripts and share them with us.<br />"
.."Help to build happy VLC community :o)</div>"
.."<pre>     www<br />"
.."    (. .)<br />"
.."-ooo-(_)-ooo-</pre>"
	w5=w:add_html(help_text,1,5,3,1)
	w14 = w:add_button("HELP (x)", click_HELPx,3,4,1,1)
	w:update()
end
function click_HELPx()
	w:del_widget(w5)
	w:del_widget(w14)
	w5=nil
	w14=nil
	w:update()
end

function meta_changed()
	vlc.msg.dbg("function meta_changed")
end

function playing_changed()
	vlc.msg.dbg("function playing_changed")
end
